//
//  HJPhotoBrowser.m
//  KaiChat
//
//  Created by lx on 2023/10/30.
//

#import "HJPhotoBrowser.h"
#import "HJAssetPreviewCell.h"
#import "TUIDefine.h"
#import "HJButton.h"

#define kPhotoViewPadding 8

@interface HJPhotoBrowser ()<UICollectionViewDataSource, UICollectionViewDelegate, UIGestureRecognizerDelegate, CAAnimationDelegate>

@property (nonatomic, strong) UICollectionView *collectionView;
@property (nonatomic, strong) UICollectionViewFlowLayout *flowLayout;
@property (nonatomic, assign) CGPoint startLocation;
@property (nonatomic, assign) CGRect startFrame;
@property (nonatomic, weak) HJPhotoPreviewCell *displayCell;
@property (nonatomic, strong) NSArray <HJPhotoItem *>*photoItems;
@property (nonatomic, assign) NSInteger selectedIndex;
@property (nonatomic, assign) NSInteger lastIndex;
@property (nonatomic, assign) BOOL viewIsAppear;
@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@property (nonatomic, assign) NSInteger preloadCount;
@property (nonatomic, weak) UIView *bottomToolView;

@end

@implementation HJPhotoBrowser

+ (instancetype)browserWithPhotoItems:(NSArray<HJPhotoItem *> *)photoItems selectedIndex:(NSUInteger)selectedIndex {
    HJPhotoBrowser *photoBrowser = [[HJPhotoBrowser alloc] init];
    photoBrowser.photoItems = photoItems;
    photoBrowser.selectedIndex = selectedIndex;
    return photoBrowser;
}

- (void)showFromViewController:(UIViewController *)vc {
    [vc presentViewController:self animated:NO completion:nil];
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        self.modalPresentationStyle = UIModalPresentationCustom;
//        self.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _lastIndex = -1;
    _preloadCount = 2;
    self.view.backgroundColor = UIColor.clearColor;
    [self addCollectionView];
    [self addGestureRecognizer];
    [self addBottomToolView];
 
}

- (void)addBottomToolView {
    UIView *bottomToolView = [UIView addToView:self.view];
    _bottomToolView = bottomToolView;
    
    HJButton *downloadButton = [HJButton addToView:bottomToolView];
    downloadButton.backgroundColor = UIColorMake(0x6A6A6A);
    downloadButton.addCornerRadius(5);
    [downloadButton setImage:[UIImage imageNamed:@"download_icon"] forState:UIControlStateNormal];
    [downloadButton addTarget:self action:@selector(didClickDownloadButton) forControlEvents:UIControlEventTouchUpInside];
    [downloadButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.inset(leftRightMargin);
        make.centerY.offset(0);
        make.width.height.offset(30);
    }];
}

- (void)didClickDownloadButton {
    UIImageWriteToSavedPhotosAlbum(self.displayCell.photoPreviewView.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    if(error) {
        [HJHUD showErrorMessage:@"Save failed"];
    } else {
        [HJHUD showSucceedMessage:@"Saved successfully"];
    }
}


- (void)addGestureRecognizer {
    
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPan:)];
    pan.delaysTouchesBegan = YES;
    pan.delaysTouchesEnded = YES;
    pan.maximumNumberOfTouches = 1;
    pan.cancelsTouchesInView = YES;
    pan.delegate = self;
    
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didSingleTap:)];
    singleTap.delaysTouchesBegan = YES;
    singleTap.delaysTouchesEnded = YES;
    singleTap.delegate = self;
    singleTap.numberOfTouchesRequired = 1;
    singleTap.numberOfTapsRequired = 1;
    
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didDoubleTap:)];
    doubleTap.delaysTouchesBegan = YES;
    doubleTap.delaysTouchesEnded = YES;
    doubleTap.numberOfTouchesRequired = 1;
    doubleTap.numberOfTapsRequired = 2;
    doubleTap.delegate = self;
    
    self.view.multipleTouchEnabled = YES;
    
    [singleTap requireGestureRecognizerToFail:doubleTap];
    [singleTap requireGestureRecognizerToFail:pan];
    
    [self.view addGestureRecognizer:singleTap];
    [self.view addGestureRecognizer:doubleTap];
    [self.view addGestureRecognizer:pan];
}

- (void)didSingleTap:(UITapGestureRecognizer *)tap {
    [self.displayCell didSingleTap:tap];
    [self showDismissAnimation];
}

- (void)showControllView:(BOOL)show animation:(BOOL)animation {
    void (^animations)(void) = ^(void) {
        if (show) {
            self.bottomToolView.alpha = 1;
        } else {
            self.bottomToolView.alpha = 0;
        }
    };
    
    if (animation) {
        [UIView animateWithDuration:0.2 animations:animations];
    } else {
        animations();
    }
}

- (void)didDoubleTap:(UITapGestureRecognizer *)tap {
    [self.displayCell didDoubleTap:tap];
}

- (void)didPan:(UIPanGestureRecognizer *)pan {
    
    CGPoint point = [pan translationInView:self.view];
    CGPoint location = [pan locationInView:self.view];
    CGPoint velocity = [pan velocityInView:self.view];
    
    NSLog(@"self.displayCell = %@", self.displayCell);
    
    TJLog(@"%s", __func__);
    
    switch (pan.state) {
        case UIGestureRecognizerStateBegan:
            _startLocation = location;
            self.startFrame = self.displayCell.animationView.frame;
            [self handlePanBegin];
            break;
        case UIGestureRecognizerStateChanged: {
            
            double percent = 1 - fabs(point.y) / (self.view.frame.size.height * 0.7);
            double s = MAX(percent, 0.3);
            
            CGFloat width = self.startFrame.size.width * s;
            CGFloat height = self.startFrame.size.height * s;
            
            CGFloat rateX = (_startLocation.x - self.startFrame.origin.x) / self.startFrame.size.width;
            CGFloat x = location.x - width * rateX;
            
            CGFloat rateY = (_startLocation.y - self.startFrame.origin.y) / self.startFrame.size.height;
            CGFloat y = location.y - height * rateY;
            
            self.displayCell.animationView.frame = CGRectMake(x, y, width, height);
            self.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:percent];
            
        }
            break;
        case UIGestureRecognizerStateEnded:
        case UIGestureRecognizerStateCancelled: {
            if (fabs(point.y) > 150 || fabs(velocity.y) > 500) {
                [self showDismissAnimation];
            } else {
                [self showCancellationAnimation];
            }
        }
            break;
        default:
            break;
    }
}

- (void)showCancellationAnimation {
    [UIView animateWithDuration:0.35 animations:^{
        self.displayCell.animationView.frame = self.startFrame;
        self.view.backgroundColor = [UIColor blackColor];
    } completion:^(BOOL finished) {
        [self showControllView:YES animation:YES];
    }];
}

- (void)showDismissAnimation {
    
    [UIApplication sharedApplication].statusBarHidden = NO;
    [self showControllView:NO animation:YES];
    UIView *sourceView = self.displayCell.item.sourceView;
    if (!sourceView) {
        [UIView transitionWithView:self.view duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
            self.view.alpha = 0;
        } completion:^(BOOL finished) {
            [self dismissController];
        }];
        return;
    }
    
    [self.collectionView layoutIfNeeded];
    
    HJPhotoItem *item = self.displayCell.item;
    
    UIView *animationView = self.displayCell.animationView;
    CGRect sourceRect = [sourceView.superview convertRect:sourceView.frame toView:self.displayCell.containView];
    [UIView animateWithDuration:0.25 animations:^{
        animationView.frame = sourceRect;
        animationView.layer.cornerRadius = item.sourceView.layer.cornerRadius;
        self.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0];
    } completion:^(BOOL finished) {
        [self dismissController];
    }];
}


- (void)dismissController {
    [self.displayCell stop];
    self.displayCell.animationView.hidden = YES;
    [self.downloadTask cancel];
    self.downloadTask = nil;
    [self dismissViewControllerAnimated:NO completion:nil];
}

- (void)handlePanBegin {
    [self showControllView:NO animation:YES];
}

- (void)didClickCloseButton {
    [self handlePanBegin];
    [self showDismissAnimation];
}

 
- (void)addCollectionView {
    
    _flowLayout = [[UICollectionViewFlowLayout alloc] init];
    _flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    _flowLayout.minimumInteritemSpacing = 0;
    _flowLayout.minimumLineSpacing = 0;
    _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_flowLayout];
    _collectionView.backgroundColor = [UIColor clearColor];
    _collectionView.dataSource = self;
    _collectionView.delegate = self;
    _collectionView.pagingEnabled = YES;
    _collectionView.scrollsToTop = NO;
    _collectionView.bounces = NO;
    _collectionView.showsHorizontalScrollIndicator = NO;
    _collectionView.contentOffset = CGPointMake(0, 0);
    _collectionView.hidden = YES;
 
    [self.view addSubview:_collectionView];
    [_collectionView registerClass:[HJPhotoPreviewCell class] forCellWithReuseIdentifier:@"HJPhotoPreviewCell"];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.photoItems.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    HJPhotoItem *item = self.photoItems[indexPath.row];
    
    HJPhotoPreviewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"HJPhotoPreviewCell" forIndexPath:indexPath];
    cell.item = item;
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(HJAssetPreviewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    
    NSLog(@"willDisplayCell = %@, indexPath = %@", cell, indexPath);
    if (!_viewIsAppear) {
        return;
    }
    
    HJPhotoPreviewCell *photoCell = (HJPhotoPreviewCell *)cell;
    photoCell.photoPreviewView.zoomScale = 1;
    [cell showControllView:YES animation:NO];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        BOOL dragToDragStop = scrollView.tracking && !scrollView.dragging && !scrollView.decelerating;
        if (dragToDragStop) {
            [self scrollViewDidStopScroll:scrollView];
        }
    }
}

- (void)scrollViewDidStopScroll:(UIScrollView *)scrollView {
    
    self.selectedIndex = scrollView.contentOffset.x / scrollView.frame.size.width;
    self.displayCell = (HJPhotoPreviewCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:self.selectedIndex inSection:0]];
    [self preloadWithPage:self.selectedIndex];
    self.lastIndex = self.selectedIndex;
}
 

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    BOOL scrollToScrollStop = !scrollView.tracking && !scrollView.dragging && !scrollView.decelerating;
    if (scrollToScrollStop) {
        [self scrollViewDidStopScroll:scrollView];
    }
}


- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    _collectionView.frame = CGRectMake(-kPhotoViewPadding, 0, self.view.bounds.size.width + kPhotoViewPadding * 2, self.view.bounds.size.height);
    _flowLayout.itemSize = _collectionView.bounds.size;
    _bottomToolView.frame = CGRectMake(0, KScreenHeight - TabbarSafeBottomMargin - 10 - 30, KScreenWidth, 30);
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    
    UIApplication.sharedApplication.statusBarHidden = YES;
    
    if (_selectedIndex > _photoItems.count - 1) {
        self.selectedIndex = 0;
    }

    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.selectedIndex inSection:0];
 
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
    [self preloadWithPage:self.selectedIndex];
    dispatch_async_main_queue(^{
        
        [self.collectionView setNeedsLayout];
        [self.collectionView layoutIfNeeded];
        self.displayCell = self.collectionView.visibleCells.firstObject;

        HJPhotoItem *selectItem = self.displayCell.item;
        UIView *sourceView = selectItem.sourceView;
        self.collectionView.hidden = NO;

        if (sourceView) {
            UIView *animationView = self.displayCell.animationView;
            CGRect endRect = animationView.frame;
            
            CGRect startRect = [sourceView.superview convertRect:sourceView.frame toView:self.view];
            startRect = CGRectMake(ceilf(startRect.origin.x), ceilf(startRect.origin.y), ceilf(startRect.size.width), ceilf(startRect.size.height));
            animationView.frame = startRect;
            
            [UIView animateWithDuration:0.45 delay:0 usingSpringWithDamping:0.75
                  initialSpringVelocity:0.7 options:UIViewAnimationOptionCurveLinear animations:^{
                animationView.frame = endRect;
                self.view.backgroundColor = UIColor.blackColor;
                
            } completion:^(BOOL finished) {
                self.displayCell = (HJPhotoPreviewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
            }];
        } else {
            self.view.backgroundColor = UIColor.blackColor;
            [UIView transitionWithView:self.view duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
            } completion:^(BOOL finished) {
                self.displayCell = (HJPhotoPreviewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
            }];
        }
    });
 
    _viewIsAppear = YES;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
    [UIApplication sharedApplication].statusBarHidden = NO;
}


- (void)preloadWithPage:(NSInteger)page {
    NSInteger left = -(_preloadCount / 2), right = _preloadCount - ABS(left);
    for (NSInteger i = left; i <= right; ++i) {
        if (i == 0) continue;
        if (page + i < self.photoItems.count) {
            HJPhotoItem *photoItem = self.photoItems[page + i];
            if ([photoItem respondsToSelector:@selector(loadData)]) {
                [photoItem loadData];
            }
        }
    }
}

- (void)clearMemory  {

}

- (void)dealloc {
    [self clearMemory];
    TJLog(@"%s", __func__);
}

@end
